<template>
  <div class="messages-container">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>即时消息</span>
        </div>
      </template>

      <div class="chat-layout">
        <!-- 设备列表 -->
        <div class="devices-list">
          <el-input
            v-model="searchKeyword"
            placeholder="搜索设备"
            prefix-icon="Search"
            clearable
            @input="searchDevices"
          />
          
          <div class="device-items">
            <div 
              v-for="device in filteredDeviceList" 
              :key="device.id" 
              class="device-item"
              :class="{ active: currentChat && currentChat.id === device.id }"
              @click="selectChat(device)"
            >
              <div class="avatar">
                <el-avatar :size="40">{{ device.deviceName.charAt(0).toUpperCase() }}</el-avatar>
                <div class="status-dot" :class="{ online: device.status === 1 }"></div>
              </div>
              <div class="info">
                <div class="name">{{ device.deviceName }}</div>
                <div class="ip-address">{{ device.ipAddress }}</div>
              </div>
              <div class="unread" v-if="device.unreadCount > 0">{{ device.unreadCount }}</div>
            </div>
            <el-empty v-if="filteredDeviceList.length === 0" description="暂无设备" :image-size="80"></el-empty>
          </div>
        </div>

        <!-- 聊天区域 -->
        <div class="chat-area">
          <template v-if="currentChat">
            <div class="chat-header">
              <span>{{ currentChat.deviceName }}</span>
              <el-tag size="small" :type="currentChat.status === 1 ? 'success' : 'info'">
                {{ currentChat.status === 1 ? '在线' : '离线' }}
              </el-tag>
            </div>
            
            <div class="message-list" ref="messageList">
              <div v-for="msg in currentMessages" :key="msg.id" class="message-item" :class="{ 'self': msg.self }">
                <div class="message-avatar">
                  <el-avatar :size="36">{{ msg.senderName.charAt(0).toUpperCase() }}</el-avatar>
                </div>
                <div class="message-content">
                  <div class="message-info">
                    <span class="sender">{{ msg.senderName }}</span>
                    <span class="time">{{ formatTime(msg.createTime) }}</span>
                  </div>
                  <div class="message-text">{{ msg.content }}</div>
                </div>
              </div>
              <div v-if="currentMessages.length === 0" class="no-messages">
                <el-empty description="暂无消息记录" :image-size="100"></el-empty>
              </div>
            </div>
            
            <div class="message-input">
              <el-input
                v-model="messageText"
                type="textarea"
                :rows="3"
                placeholder="输入消息..."
                @keydown.enter.prevent="sendMessage"
              />
              <div class="input-actions">
                <el-button type="primary" @click="sendMessage" :disabled="!messageText.trim()">发送</el-button>
                <el-button @click="openFileUpload">发送文件</el-button>
                <input 
                  type="file" 
                  ref="fileInput" 
                  style="display: none" 
                  @change="handleFileChange" 
                />
              </div>
            </div>
          </template>
          
          <div v-else class="no-chat-selected">
            <el-empty description="请选择一个设备开始聊天" :image-size="120"></el-empty>
          </div>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script setup>
import { ref, computed, nextTick, onMounted, onUnmounted } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { getOnlineDevices } from '@/api/device';
import { sendMessage as sendMessageAPI, getMessagesBetween, markAllAsRead, getUnreadCount } from '@/api/message';
import { uploadFile, createFileTransfer } from '@/api/fileTransfer';
import { useDeviceStore } from '@/store/deviceStore';
import dayjs from 'dayjs';

const deviceStore = useDeviceStore();
const deviceList = ref([]);
const filteredDeviceList = ref([]);
const searchKeyword = ref('');
const currentChat = ref(null);
const currentMessages = ref([]);
const messageText = ref('');
const messageList = ref(null);
const fileInput = ref(null);
const websocket = ref(null);

// 格式化时间
const formatTime = (time) => {
  return dayjs(time).format('HH:mm:ss');
};

// 加载设备列表
const loadDeviceList = async () => {
  try {
    const res = await getOnlineDevices();
    const devices = res.data.filter(device => device.id !== deviceStore.currentDevice.id);
    
    deviceList.value = await Promise.all(devices.map(async device => {
      // 获取未读消息数
      const unreadRes = await getUnreadCount(deviceStore.currentDevice.id);
      return {
        ...device,
        unreadCount: unreadRes.data || 0
      };
    }));
    
    filteredDeviceList.value = [...deviceList.value];
  } catch (error) {
    console.error('加载设备列表失败:', error);
    ElMessage.error('加载设备列表失败');
  }
};

// 搜索设备
const searchDevices = () => {
  if (!searchKeyword.value) {
    filteredDeviceList.value = [...deviceList.value];
    return;
  }
  
  const keyword = searchKeyword.value.toLowerCase();
  filteredDeviceList.value = deviceList.value.filter(device => {
    return device.deviceName.toLowerCase().includes(keyword) ||
           device.ipAddress.toLowerCase().includes(keyword);
  });
};

// 选择聊天
const selectChat = async (device) => {
  currentChat.value = device;
  // 加载聊天记录
  await loadChatHistory(device.id);
  // 标记消息为已读
  await markAllAsRead(device.id, deviceStore.currentDevice.id);
  // 清除未读计数
  const index = deviceList.value.findIndex(item => item.id === device.id);
  if (index !== -1) {
    deviceList.value[index].unreadCount = 0;
  }
};

// 加载聊天历史
const loadChatHistory = async (targetDeviceId) => {
  try {
    const res = await getMessagesBetween(
      deviceStore.currentDevice.id, 
      targetDeviceId
    );
    currentMessages.value = res.data;
    
    // 滚动到底部
    nextTick(() => {
      if (messageList.value) {
        messageList.value.scrollTop = messageList.value.scrollHeight;
      }
    });
  } catch (error) {
    console.error('加载聊天记录失败:', error);
    ElMessage.error('加载聊天记录失败');
  }
};

// 发送消息
const sendMessage = async () => {
  if (!messageText.value.trim()) return;
  
  try {
    const messageData = {
      senderId: deviceStore.currentDevice.id,
      senderName: deviceStore.currentDevice.deviceName,
      receiverId: currentChat.value.id,
      receiverName: currentChat.value.deviceName,
      content: messageText.value,
      type: 0 // 文本消息
    };
    
    await sendMessageAPI(messageData);
    messageText.value = '';
    
    // 重新加载消息
    await loadChatHistory(currentChat.value.id);
  } catch (error) {
    console.error('发送消息失败:', error);
    ElMessage.error('发送消息失败');
  }
};

// 打开文件选择
const openFileUpload = () => {
  fileInput.value.click();
};

// 处理文件选择
const handleFileChange = async (event) => {
  const file = event.target.files[0];
  if (!file) return;
  
  try {
    ElMessage.info('正在上传文件...');
    
    // 上传文件
    const uploadRes = await uploadFile(file);
    
    // 创建文件传输记录
    const fileTransferData = {
      senderId: deviceStore.currentDevice.id,
      receiverId: currentChat.value.id,
      fileName: file.name,
      fileSize: file.size
    };
    
    const transferRes = await createFileTransfer(fileTransferData);
    
    // 发送文件消息
    const messageData = {
      senderId: deviceStore.currentDevice.id,
      senderName: deviceStore.currentDevice.deviceName,
      receiverId: currentChat.value.id,
      receiverName: currentChat.value.deviceName,
      content: `文件: ${file.name} (${formatFileSize(file.size)}) [传输密钥: ${transferRes.data.transferKey}]`,
      type: 2 // 文件消息
    };
    
    await sendMessageAPI(messageData);
    
    // 清空文件输入
    event.target.value = '';
    
    // 重新加载消息
    await loadChatHistory(currentChat.value.id);
    
    ElMessage.success('文件发送成功');
  } catch (error) {
    console.error('文件发送失败:', error);
    ElMessage.error('文件发送失败');
  }
};

// 格式化文件大小
const formatFileSize = (size) => {
  if (size < 1024) {
    return size + ' B';
  } else if (size < 1024 * 1024) {
    return (size / 1024).toFixed(2) + ' KB';
  } else if (size < 1024 * 1024 * 1024) {
    return (size / (1024 * 1024)).toFixed(2) + ' MB';
  } else {
    return (size / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
  }
};

// 初始化WebSocket
const initWebSocket = () => {
  const wsUrl = `ws://${window.location.hostname}:${window.location.port}/ws/${deviceStore.currentDevice.id}`;
  websocket.value = new WebSocket(wsUrl);
  
  websocket.value.onopen = () => {
    console.log('WebSocket连接已建立');
  };
  
  websocket.value.onmessage = (event) => {
    const message = JSON.parse(event.data);
    
    // 如果是当前聊天的消息，直接添加到消息列表
    if (currentChat.value && message.senderId === currentChat.value.id) {
      loadChatHistory(currentChat.value.id);
      // 标记为已读
      markAllAsRead(message.senderId, deviceStore.currentDevice.id);
    } else {
      // 更新未读消息计数
      loadDeviceList();
      // 提示新消息
      ElMessage({
        message: `收到来自 ${message.senderName} 的新消息`,
        type: 'info'
      });
    }
  };
  
  websocket.value.onerror = (error) => {
    console.error('WebSocket错误:', error);
  };
  
  websocket.value.onclose = () => {
    console.log('WebSocket连接已关闭');
  };
};

onMounted(async () => {
  await loadDeviceList();
  initWebSocket();
  
  // 定时刷新设备列表
  const interval = setInterval(loadDeviceList, 30000);
  
  onUnmounted(() => {
    clearInterval(interval);
    if (websocket.value) {
      websocket.value.close();
    }
  });
});
</script>

<style scoped>
.messages-container {
  padding: 20px;
  height: calc(100vh - 140px);
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.chat-layout {
  display: flex;
  height: calc(100vh - 220px);
  border: 1px solid #ebeef5;
  border-radius: 4px;
}

.devices-list {
  width: 280px;
  border-right: 1px solid #ebeef5;
  display: flex;
  flex-direction: column;
}

.device-items {
  flex: 1;
  overflow-y: auto;
  padding: 10px 0;
}

.device-item {
  display: flex;
  align-items: center;
  padding: 10px 15px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.device-item:hover {
  background-color: #f5f7fa;
}

.device-item.active {
  background-color: #ecf5ff;
}

.avatar {
  position: relative;
  margin-right: 10px;
}

.status-dot {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #909399;
  border: 2px solid #fff;
}

.status-dot.online {
  background-color: #67c23a;
}

.info {
  flex: 1;
}

.name {
  font-weight: bold;
  margin-bottom: 4px;
}

.ip-address {
  font-size: 12px;
  color: #909399;
}

.unread {
  background-color: #f56c6c;
  color: white;
  border-radius: 50%;
  min-width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  padding: 0 5px;
}

.chat-area {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.chat-header {
  padding: 10px 20px;
  border-bottom: 1px solid #ebeef5;
  display: flex;
  align-items: center;
}

.chat-header span {
  font-weight: bold;
  margin-right: 10px;
}

.message-list {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}

.message-item {
  display: flex;
  margin-bottom: 15px;
}

.message-item.self {
  flex-direction: row-reverse;
}

.message-avatar {
  margin: 0 10px;
}

.message-content {
  max-width: 70%;
}

.message-item.self .message-content {
  text-align: right;
}

.message-info {
  margin-bottom: 5px;
}

.sender {
  font-weight: bold;
  margin-right: 10px;
}

.time {
  font-size: 12px;
  color: #909399;
}

.message-text {
  background-color: #f5f7fa;
  padding: 10px;
  border-radius: 4px;
  word-break: break-word;
}

.message-item.self .message-text {
  background-color: #ecf5ff;
}

.message-input {
  padding: 10px 20px;
  border-top: 1px solid #ebeef5;
}

.input-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}

.input-actions button {
  margin-left: 10px;
}

.no-chat-selected, .no-messages {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style> 